package com.linfeng.component.mybatisplus.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.linfeng.component.common.response.ResponseEntity;
import com.linfeng.component.mybatisplus.event.cmd.CreateCmd;
import com.linfeng.component.mybatisplus.event.cmd.UpdateCmd;
import com.linfeng.component.mybatisplus.event.qry.PageQry;
import com.linfeng.component.mybatisplus.service.BaseService;
import com.linfeng.component.mybatisplus.tools.PageTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;

public abstract class Controller<PV, DV, D, CC extends CreateCmd, UC extends UpdateCmd, S extends BaseService<D, CC, UC>> {

    protected Class<PV> pageVOClass = this.currentPageVOClass();

    protected Class<DV> dvClass = this.currentDetailVOClass();

    @Autowired
    protected S baseService;

    @GetMapping(value = "/v1/page")
    public <Q extends PageQry> ResponseEntity<IPage<PV>> page(Q q) {

        IPage<D> page = baseService.page(q);

        return ResponseEntity.body(PageTools.convertPage(page, pageVOClass));
    }

    @PostMapping(value = "/v1")
    public ResponseEntity create(@RequestBody CC cmd) {

        return ResponseEntity.body(baseService.create(cmd));
    }

    @GetMapping(value = "/v1/{id}")
    public ResponseEntity<DV> detail(@PathVariable(value = "id") Serializable id) {

        return ResponseEntity.body(BeanUtil.copyProperties(baseService.detail(id), dvClass));
    }

    @PutMapping(value = "/v1")
    public ResponseEntity update(@RequestBody UC cmd) {

        return ResponseEntity.body(baseService.update(cmd));
    }


    private Class<PV> currentPageVOClass() {

        return (Class<PV>) ReflectionKit.getSuperClassGenericType(this.getClass(), Controller.class, 0);
    }

    private Class<DV> currentDetailVOClass() {

        return (Class<DV>) ReflectionKit.getSuperClassGenericType(this.getClass(), Controller.class, 1);
    }
}
